import java.io.*;   
import java.net.*;
import java.util.*;

public class Client {
  public static void main(String[] args) throws IOException { 
    if (args.length < 3) {
      System.err.println("Parametros: <host> <porta_server> <porta_client> <diretorio>");
      System.exit(1);
    }

    String hostServer = args[0];
    int portServer = Integer.parseInt(args[1]);
    int numero;

    File[] files; 
    Scanner scan = new Scanner(System.in);
    String line;
    String[] processedLine;
    String hostP2P;
    int portP2P;

    try {
      Socket socketServ = new Socket(hostServer, portServer); 
      Socket socketCli;
      BufferedReader inServ = new BufferedReader(new InputStreamReader(socketServ.getInputStream()));
      BufferedReader inCli;
      PrintWriter outServ = new PrintWriter(socketServ.getOutputStream(), true);
      PrintWriter outCli;
      ClientThread ct = new ClientThread(Integer.parseInt(args[2]), args[3]);
      int size;
      ct.start();
      File directory = new File("./"+args[3]);
      if (!directory.isDirectory()) {
        directory.mkdir();
      }
      outServ.println("new "+args[2]+" "+args[3]);
      numero = Integer.parseInt(inServ.readLine());
      files = directory.listFiles();
      for (int i = 0; i < files.length; i++){
        outServ.println("add "+files[i]+" "+numero);
      }
      do {
        line = scan.nextLine();
        outServ.println(line);
        processedLine = line.split(" ");
        switch(processedLine[0]) {
          case "files":
            size = Integer.parseInt(inServ.readLine());
            for (int i = 0; i < size; i++) {
              System.out.println(inServ.readLine());
            }
            break;
          case "clients":
            size = Integer.parseInt(inServ.readLine());
            for (int i = 0; i < size; i++) {
              System.out.println(inServ.readLine());
            }
            break;
          case "read":
            if (Integer.parseInt(inServ.readLine()) == 1) {
              hostP2P = inServ.readLine();
              portP2P = Integer.parseInt(inServ.readLine());
              System.out.println("host: "+hostP2P+"\nporta: "+portP2P);
              socketCli = new Socket(hostP2P, portP2P);
              inCli = new BufferedReader(new InputStreamReader(socketCli.getInputStream()));
              outCli = new PrintWriter(socketCli.getOutputStream(), true);
              outCli.println(line);
              if (Integer.parseInt(inCli.readLine()) == 0) {
                System.out.println("Não foi possível ler o arquivo.");
              } else {
                String l = "";
                while ( l != null){
                  l = inCli.readLine();
                  System.out.println(l);
                }
              }
            } else {
              System.out.println("Não foi possível ler o arquivo.");
            }
            break;
          case "create":
            if (Integer.parseInt(inServ.readLine()) == 1) {
              hostP2P = inServ.readLine();
              portP2P = Integer.parseInt(inServ.readLine());
              System.out.println("host: "+hostP2P+"\nporta: "+portP2P);
              socketCli = new Socket(hostP2P, portP2P);
              inCli = new BufferedReader(new InputStreamReader(socketCli.getInputStream()));
              outCli = new PrintWriter(socketCli.getOutputStream(), true);
              outCli.println(line);
              if (Integer.parseInt(inCli.readLine()) == 0) {
                System.out.println("Não foi possível criar o arquivo.");
              } else {
                System.out.println("O arquivo "+processedLine[1]+" foi criado com sucesso no cliente "+processedLine[2]+".");
                outServ.println("add ./"+inCli.readLine()+"/"+processedLine[1]+" "+processedLine[2]);
              }
            } else {
              System.out.println("Não foi possível criar o arquivo.");
            }
            break;
          case "remove":
            if (Integer.parseInt(inServ.readLine()) == 1) {
              hostP2P = inServ.readLine();
              portP2P = Integer.parseInt(inServ.readLine());
              System.out.println("host: "+hostP2P+"\nporta: "+portP2P);
              socketCli = new Socket(hostP2P, portP2P);
              inCli = new BufferedReader(new InputStreamReader(socketCli.getInputStream()));
              outCli = new PrintWriter(socketCli.getOutputStream(), true);
              outCli.println(line);
              outServ.println(inCli.readLine());
              outServ.flush();
            } else {
              System.out.println("Não foi possível remover o arquivo.");
            }
            break;
          case "move":
            outServ.println("remove "+processedLine[1]+" "+processedLine[2]);
            if (Integer.parseInt(inServ.readLine()) == 1) {
              hostP2P = inServ.readLine();
              portP2P = Integer.parseInt(inServ.readLine());
              System.out.println("host: "+hostP2P+"\nporta: "+portP2P);
              socketCli = new Socket(hostP2P, portP2P);
              inCli = new BufferedReader(new InputStreamReader(socketCli.getInputStream()));
              outCli = new PrintWriter(socketCli.getOutputStream(), true);
              outCli.println(line);
              if (Integer.parseInt(inCli.readLine()) == 1) {
                getFile("./"+args[3]+"/"+processedLine[1], socketCli);
                outServ.println("1");
                outServ.flush();
                outServ.println("add "+"./"+args[3]+"/"+processedLine[1]+" "+numero);
              } else {
                outServ.println("0");
                outServ.flush();
              }
            } else {
              System.out.println("Não foi possível mover o arquivo.");
            }
            break;
          case "exit":
            outServ.println(Integer.toString(numero));
            break;
        }
      } while (!line.equals("exit"));
      socketServ.close();
      System.exit(-1);
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(-1);
    }
  }

  public static void getFile(String filename, Socket socket) throws Exception {
    int filesize = 1022386;
    int bytesRead;
    int currentTot = 0;
    byte [] bytearray = new byte [filesize];
    InputStream is = socket.getInputStream();
    FileOutputStream fos = new FileOutputStream(filename);
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    bytesRead = is.read(bytearray, 0, bytearray.length);
    currentTot = bytesRead;

    do {
      bytesRead = is.read(bytearray, currentTot, (bytearray.length - currentTot));
      if(bytesRead >= 0) currentTot += bytesRead;
    } while(bytesRead > -1);

    bos.write(bytearray, 0, currentTot);
    bos.flush();
    bos.close();
  }
}